package com.yf.esms.service;

import com.yf.esms.model.vo.ReportVo;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author 99698
 */
@Service
public class SearchService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    private static final String INDEX = "customer";

    public ReportVo searchById(String id) throws IOException {
        GetRequest getRequest = new GetRequest(INDEX);
        getRequest.id(id);
        GetResponse documentFields = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        String name = (String)documentFields.getSource().get("name");
        ReportVo reportVo = new ReportVo();
        reportVo.setName(name);
        return reportVo;
    }

    public List<ReportVo> searchByKeyword(String keyword) throws IOException {
        SearchRequest searchRequest = new SearchRequest(INDEX);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        if (StringUtils.isNotEmpty(keyword)){
            QueryBuilder name = QueryBuilders.matchQuery("name", keyword);
            boolQueryBuilder.must(name);
            searchSourceBuilder.query(boolQueryBuilder).sort("_score", SortOrder.DESC).trackTotalHits(true);
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.requireFieldMatch(true);
            highlightBuilder.field("name");
            highlightBuilder.preTags("<font color='red'>");
            highlightBuilder.postTags("</font>");
            searchRequest.source(searchSourceBuilder);

            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            ArrayList<Map<String, Object>> list = new ArrayList<>();
            // 获取数据总数total
            long total = searchResponse.getHits().getTotalHits().value;
            // 获取文档数据
            SearchHit[] hits = searchResponse.getHits().getHits();

            for (SearchHit searchHit : hits) {
                Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                HighlightField nameField = highlightFields.get("name");
                Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
                if (null != nameField){
                    //获取该高亮字段信息
                    Text[] nameFragments = nameField.getFragments();
                    String newName = "";
                    for (Text nameFragment : nameFragments) {
                        newName += nameFragment;
                    }
                    //将高亮后的值替换掉旧值
                    sourceAsMap.put("name", newName);
                }
                list.add(sourceAsMap);
            }
            List<ReportVo> reportVos = new ArrayList<>();
            for (Map<String, Object> map : list) {
                ReportVo reportVo = new ReportVo();
                reportVo.setName((String)map.get("name"));
                reportVos.add(reportVo);
            }
            return reportVos;
        }else {
            return new ArrayList<>();
        }
    }
}
